import React, { useContext, useReducer } from 'react'
import consoleUtil from '@/utils/consoleUtil'

// 创建一个上下文对象，用于组件间传递数据
const ApplicationContext = React.createContext()

// 导出上下文对象，以便其他组件可以使用
export default ApplicationContext

// 状态更新的reducer函数
const contextReducer = (state, action) => {
    switch (action.type) {
        case 'SET_CONTEXT_VALUE':
            return { ...state, ...action.payload }
        default:
            return state
    }
}

//导出一个上下文提供者组件，用于包裹需要传递数据的组件树
export const MyContextProvider = ({ initialState, children }) => {
    const [state, dispatch] = useReducer(contextReducer, initialState || {})
    // 定义一个更新上下文值的方法，允许外部更新状态
    const setContextValue = (obj) => {
        if (obj && typeof obj === 'object') {
            dispatch({ type: 'SET_CONTEXT_VALUE', payload: obj })
        } else {
            consoleUtil.error('Invalid or empty context value:', obj)
        }
    }

    // 渲染组件，将当前状态和更新状态的方法传递给子组件
    try {
        return (
            <ApplicationContext.Provider value={{ ...state, setContextValue }}>
                {children}
            </ApplicationContext.Provider>
        )
    } catch (error) {
        consoleUtil.error('Error rendering MyContextProvider:', error)
        return null
    }
}


/**
 * 获取上下文并将其映射到组件属性
 * 
 * @param {React.Component} Component - 需要包装的React组件
 * @param {Function} mapToProps - 将上下文映射到组件属性的函数
 * @returns {React.Component} - 返回一个包装了给定组件的高阶组件
 */
export const getContext = (Component, mapToProps) => {
    // 检查组件是否为有效的React组件
    if (typeof Component !== 'function' || Component == null) {
        throw new Error('Component must be a valid React component')
    }
    // 返回一个高阶组件，用于包装给定的组件
    return (props) => {
        try {
            // 尝试获取上下文
            const context = useContext(ApplicationContext)
            // 如果上下文未定义，则输出错误信息并返回null
            if (!context) {
                consoleUtil.error('Context is undefined')
                return null
            }
            // 根据mapToProps函数处理上下文，如果mapToProps不是函数，则直接使用context
            let mappedContext = typeof mapToProps === 'function' ? mapToProps(context) : context
            // 使用props和mappedContext渲染组件
            return <Component {...props} {...mappedContext} />
        } catch (error) {
            // 捕获并输出错误信息
            consoleUtil.error('Error in getContext HOC:', error)
            return null
        }
    }
}